﻿namespace Atomic.Data.AdoNet
{
    using System;
    using System.Data;
    using System.Data.Common;
    using System.Data.SqlClient;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    
    /// <summary>
    /// 数据提供程序扩展。
    /// </summary>
    public static class DataProviderAsyncExtensions
    {
        /// <summary>
        /// 查询数据。
        /// </summary>
        /// <typeparam name="TModelType">返回的实体类型。</typeparam>
        /// <param name="dataProvider">数据提供程序。</param>
        /// <param name="sql">SQL 语句或者存储过程名称。</param>
        /// <param name="action">获得实体的方法。</param>
        /// <param name="commandParameters">SQL 参数。</param>
        /// <returns>实体集合。</returns>
        public static async Task<IEnumerable<TModelType>> SqlQueryAsync<TModelType>(
            this IDataProvider dataProvider, string sql, Func<DbDataReader, TModelType> action, params IDataParameter[] commandParameters)
        {
            return await dataProvider.SqlQueryAsync<TModelType>(CommandType.Text, sql, action, commandParameters);
        }

        /// <summary>
        /// 查询数据。
        /// </summary>
        /// <typeparam name="TModelType">返回的实体类型。</typeparam>
        /// <param name="dataProvider">数据提供程序。</param>
        /// <param name="commandType">命令类型。</param>
        /// <param name="sql">SQL 语句或者存储过程名称。</param>
        /// <param name="action">获得实体的方法。</param>
        /// <param name="commandParameters">SQL 参数。</param>
        /// <returns>实体集合。</returns>
        public static async Task<IEnumerable<TModelType>> SqlQueryAsync<TModelType>(
            this IDataProvider dataProvider, CommandType commandType, string sql, Func<DbDataReader, TModelType> action, params IDataParameter[] commandParameters)
        {
            IList<TModelType> items = new List<TModelType>();

            using (var dataReader = await dataProvider.SqlQueryAsync(commandType, sql, commandParameters))
            {
                while (await dataReader.ReadAsync())
                {
                    var item = action(dataReader);

                    if (item != null)
                    {
                        items.Add(item);
                    }
                }
            }

            return items;
        }

        /// <summary>
        /// 查询数据。
        /// </summary>
        /// <param name="dataProvider">数据提供程序。</param>
        /// <param name="sql">SQL 语句或者存储过程名称。</param>
        /// <param name="commandParameters">SQL 参数。</param>
        /// <returns>数据读取器。</returns>
        public static async Task<DbDataReader> SqlQueryAsync(this IDataProvider dataProvider, string sql, params IDataParameter[] commandParameters)
        {
            return await dataProvider.SqlQueryAsync(CommandType.Text, sql, commandParameters);
        }

        /// <summary>
        /// 查询单条数据。
        /// </summary>
        /// <param name="dataProvider">数据提供程序。</param>
        /// <param name="sql">SQL 语句或者存储过程名称。</param>
        /// <param name="commandParameters">SQL 参数。</param>
        /// <returns>查询结果。</returns>
        public static async Task<object> SingleAsync(this IDataProvider dataProvider, string sql, params IDataParameter[] commandParameters)
        {
            return await dataProvider.SingleAsync(CommandType.Text, sql, commandParameters);
        }

        /// <summary>
        /// 查询单条数据。
        /// </summary>
        /// <typeparam name="TDataType">返回结果数据的类型。</typeparam>
        /// <param name="dataProvider">数据提供程序。</param>
        /// <param name="sql">SQL 语句或者存储过程名称。</param>
        /// <param name="commandParameters">SQL 参数。</param>
        /// <returns>查询结果。</returns>
        public static async Task<TDataType> SingleAsync<TDataType>(this IDataProvider dataProvider, string sql, params IDataParameter[] commandParameters)
        {
            var data = await dataProvider.SingleAsync(CommandType.Text, sql, commandParameters);

            if (data != null && data != DBNull.Value)
            {
                return (TDataType)data;
            }

            return default(TDataType);
        }

        /// <summary>
        /// 执行 SQL 命令。
        /// </summary>
        /// <param name="dataProvider">数据提供程序。</param>
        /// <param name="sql">SQL 语句或者存储过程名称。</param>
        /// <param name="commandParameters">SQL 参数。</param>
        /// <returns>影响行数。</returns>
        public static async Task<int> ExecuteSqlCommandAsync(this IDataProvider dataProvider, string sql, params IDataParameter[] commandParameters)
        {
            return await dataProvider.ExecuteSqlCommandAsync(CommandType.Text, sql, commandParameters);
        }
    }
}